package com.cmcc.cmii.smsim.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cmcc.cmii.smsim.base.BaseServiceImpl;

import com.cmcc.cmii.smsim.constants.LayIMConstants;
import com.cmcc.cmii.smsim.entity.*;
import com.cmcc.cmii.smsim.mapper.*;
import com.cmcc.cmii.smsim.result.ChatRecordResult;
import com.cmcc.cmii.smsim.result.GroupMemberResult;
import com.cmcc.cmii.smsim.result.InitResult;
import com.cmcc.cmii.smsim.result.JsonResult;
import com.cmcc.cmii.smsim.service.IUserService;
import com.cmcc.cmii.smsim.utils.Utils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Thanks
 * @since 2020-05-21
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserService {

    private final UserMapper userMapper;

    private final FriendGroupMapper friendGroupMapper;

    private final UserFriendGroupMapper userFriendGroupMapper;

    private final UserBigGroupMapper userBigGroupMapper;

    private final BigGroupMapper bigGroupMapper;

    private final MsgRecordMapper msgRecordMapper;

    @Override
    public JsonResult getInitResult(Long userId) {
        InitResult initResult = new InitResult();
        initResult.setMine(userMapper.selectById(userId));
        List<FriendGroup> friendGroups = friendGroupMapper.selectList(new QueryWrapper<>(FriendGroup.builder().uid(userId).build()));
        if(!CollectionUtils.isEmpty(friendGroups)){
            List<Long> friendGroupIds = friendGroups.stream().map(x -> x.getId()).collect(Collectors.toList());
            List<UserFriendGroup> userFriendGroups = userFriendGroupMapper.getUserIdsByGroupIds(friendGroupIds);
            //根据所有的用户ID查询出用户信息
            if(!CollectionUtils.isEmpty(userFriendGroups)){
                List<Long> friendIds = userFriendGroups.stream().map(x -> x.getUid()).collect(Collectors.toList());
                List<User> friends = userMapper.selectBatchIds(friendIds);
                //将用户分组
                friendGroups.stream().forEach(x->{
                    List<Long> userIdInGroup = userFriendGroups.stream().filter(u -> u.getGroupId().equals(x.getId()))
                            .map(m -> m.getUid()).collect(Collectors.toList());
                    x.setList(friends.stream().filter(f->userIdInGroup.contains(f.getId())).collect(Collectors.toList()));

                });
            }
            initResult.setFriend(friendGroups);
        }

        List<UserBigGroup> userBigGroups = userBigGroupMapper.selectList(new QueryWrapper<>(UserBigGroup.builder().uid(userId).build()));
        if(!CollectionUtils.isEmpty(userBigGroups)){
            List<BigGroup> myGroups = bigGroupMapper.getGroupsByGroupIds(userBigGroups.stream().map(x->x.getGroupId()).collect(Collectors.toList()));
            initResult.setGroup(myGroups);
        }
        return JsonResult.success(initResult);
    }

    /**
     * TODO 可以考虑用一条sql
     * @param groupId
     * @return
     */
    @Override
    public JsonResult getMembersByGroupId(Long groupId) {
        GroupMemberResult memberResult = new GroupMemberResult();
        if(groupId<0){
            return JsonResult.success(memberResult);
        }
        BigGroup bigGroup = bigGroupMapper.selectById(groupId);
        if(null!=bigGroup){
            Long uid = bigGroup.getUid();
            User user = userMapper.selectById(uid);
            memberResult.setOwner(user);
        }
        //通过组ID获取用户ID
        UserBigGroup userBigGroup = new UserBigGroup();
        userBigGroup.setGroupId(groupId);
        List<UserBigGroup> userBigGroups = userBigGroupMapper.selectList(new QueryWrapper<>(userBigGroup));
        if(!CollectionUtils.isEmpty(userBigGroups)){
            List<Long> userIds = userBigGroups.stream().map(x -> x.getUid()).collect(Collectors.toList());
            List<User> users = userMapper.selectBatchIds(userIds);
            memberResult.setList(users);
        }
        return JsonResult.success(memberResult);
    }

    @Override
    public JsonResult getChatRecords(Long userId, Long id, String type, Long lastId) {
        if(!type.equals(LayIMConstants.CHAT_TYPE_FRIEND)&&!type.equals(LayIMConstants.CHAT_TYPE_GROUP)) {
            throw new IllegalArgumentException("type should be group or friend");
        }
        boolean isChatGroup = type.equals(LayIMConstants.CHAT_TYPE_GROUP);
        IPage<MsgRecord> page = new Page<>(1,20);
        MsgRecord msgRecord = new MsgRecord();
        msgRecord.setRoomId(Utils.generateRoomId(userId,id,type));
        QueryWrapper<MsgRecord> queryWrapper = new QueryWrapper<>(msgRecord);
        queryWrapper.lt("id",lastId);
        List<ChatRecordResult> records = new ArrayList<>(20);
        IPage<MsgRecord> msgRecordIPage = msgRecordMapper.selectPage(page, queryWrapper);
        List<MsgRecord> msgRecords = msgRecordIPage.getRecords();
        if(CollectionUtils.isEmpty(msgRecords)){
            return JsonResult.success(records);
        }
        List<Long> userIds;
        if(isChatGroup){
            userIds = msgRecords.stream().map(x->x.getFromId()).distinct().collect(Collectors.toList());
        }else {
            userIds = new ArrayList<>(2);
            userIds.add(userId);
            userIds.add(id);
        }
        //获取用户
        List<User> users = userMapper.selectBatchIds(userIds);
        for (MsgRecord record : msgRecords) {
            ChatRecordResult res = new ChatRecordResult();
            res.setId(record.getId());

            Optional<User> user = users.stream().filter(x -> x.getId().equals(record.getFromId())).findFirst();
            res.setAvatar(user.orElse(User.Anonymous).getAvatar());
            res.setUsername(user.orElse(User.Anonymous).getUserName());

            res.setContent(record.getContents());
            res.setSelf(userId.equals(record.getFromId()));
            res.setTimestamp(record.getCreateAt());
            records.add(res);
        }
        Collections.sort(records);
        return JsonResult.success(records);
    }


}
